home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The PC-SIG Library 10
/
The PC-Sig Library - Shareware for the IBM PC and Compatibles (PC-SIG)(Tenth Edition Disks 1-2804)(1991).iso
/
PC_SIGCD
/
05
/
6
/
DISK0564.ZIP
/
SOURCE.ARC
/
HEAD.ASM
< prev
next >
Wrap
Assembly Source File
|
1989-01-19
|
11KB
|
411 lines
TITLE HEAD - A FILTER FOR MSDOS2
PAGE 55,132
;******************************************************************************
; THIS PROGRAM PRINTS THE FIRST FEW LINES OF A TEXT FILE.
;
; IT READS FROM A FILE IF SPECIFIED, OR FROM THE STANDARD INPUT OTHERWISE
; IT WRITES TO THE STANDARD OUTPUT.
;
; USAGE: HEAD -n file1 file2 ...
; -n is optional, limits output to n lines (20 default)
; file names can be ambiguous
;
;
; VERSION 1.8, 02-OCT-87: assembles under MASM 5.0
; VERSION 1.7, 21-DEC-86: now supports wildcards, multiple files
; VERSION 1.6, 06-SEP-86: minor cleanup, fixed bug involving failure
; to set data segment when reading from stdin.
; VERSION 1.5, 13-AUG-86: handles arbitrary -n (up to 65535)
; also now buffers output, doesn't expand tabs
; VERSION 1.4, 06-JUL-86: changes to memory allocation, now assembles
; under MASM 4.0
; VERSION 1,3, 04-FEB-86: fixed bug in reading from std. input
; VERSION 1.2, 16-JAN-86: makes UTIL and CONSOLE external modules
; VERSION 1.1, 27-SEP-85: defaults to std. input if no file given
; VERSION 1.0, 19-SEP-85
;
; BY: JON DART
; 3012 HAWTHORN ST.,
; SAN DIEGO, CA 92104
;
; TO BUILD HEAD EXE:
;
; MASM HEAD,HEAD,NUL,NUL
; LINK HEAD,HEAD,NUL,ASM
INBUFSIZE EQU 8192 ;SIZE OF INPUT BUFFER
OUTBUFSIZE EQU 512 ;SIZE OF OUTPUT BUFFER
MAXARGS EQU 40 ;MAX. # CMD. LINE ARGUMENTS
PRGSIZE EQU 1000H ;MAX. SIZE OF CODE + FIXED DATA
M EQU BYTE PTR 0[BX]
.XLIST
INCLUDE ASCII.DEF
INCLUDE MSDOS2.DEF
INCLUDE MACROS.DEF
.LIST
DOSSEG
.MODEL SMALL
; MEMORY DEFINITIONS:
;
.DATA
INHANDLE DW 0 ;INPUT FILE HANDLE
;(DEFAULTS TO STD. INPUT)
NUMARGS DW 1 ;NUMBER OF COMMAND LINE ARGUMENTS
OUTNDX DW 0 ;OFFSET TO NEXT SLOT IN OUTPUT BUFFER
NUMLIN DW 20 ;NUMBER OF LINES TO LIST
ONEFILE DB 1 ;SET 1 IF ONE UNAMBIG. ARGUMENT
MSG1 DB CR,LF,"head: can't open ",0
MSG1E DB CR,LF,0
MSG2 DB CR,LF,"head: read error on file ",0
MSG4 DB CR,LF,"head usage: head -n filename",CR,LF,0
MSG5 DB CR,LF,"head: too many command line arguments",CR,LF,0
MSG6 DB CR,LF,"head: unknown pathname ",0
; UNINITIALIZED DATA SPACE:
.DATA?
INBUF DB INBUFSIZE DUP (?) ;INPUT BUFFER
OUTBUF DB OUTBUFSIZE DUP (?) ;OUTPUT BUFFER
ARGPTRS DB (2*MAXARGS) DUP (?) ;POINTERS TO ARGUMENTS
ARGBUF DB 512 DUP (?) ;ARGUMENT BUFFER
SPATH DB 65 DUP (?) ;SEARCH PATH
PREFIX DB 65 DUP (?) ;SEARCH PREFIX
FILENAME DB 65 DUP (?) ;COMPOSITE FILE NAME (PREFIX + NAME)
DTA DB 128 DUP (?) ;DTA AREA
MAXMEM EQU DTA + 128 ;MAX. MEMORY USED
.STACK
DB 512 DUP (?)
.CODE
EXTRN COUT:NEAR,ERRORMSG:NEAR
EXTRN SKIPSP:NEAR,DTOBIN:NEAR,CPYCNT:NEAR,TYPTX:NEAR
EXTRN FIXPATH:NEAR,GETARGS:NEAR
EXTRN TYPE_UNK:ABS,TYPE_UFN:ABS
ENTRY:
TEST_DOS2 ;TEST FOR DOS 2.0, EXIT IF DOS 1
MEMOK:
MOV AX,DGROUP
MOV ES,AX ;SET EXTRA SEG TO POINT TO BUFFERS
MOV BX,80H ;GET BYTE COUNT FOR COMMAND LINE
CMP BYTE PTR [BX],0 ;TEST IT
JNE L_1 ;IF NOT 0
JMP START ;NO ARGUMENTS, USE STDIN
L_1:
PUSH BX
MOV DL,BYTE PTR [BX]
MOV DH,0
ADD BX,DX
INC BX
MOV BYTE PTR [BX],0 ;PUT 0 BYTE AT END OF COMMAND LINE
POP BX
INC BX ;POINT TO START OF COMMAND LINE
MOV SI,OFFSET ARGPTRS
MOV DI,OFFSET ARGBUF
MOV CX,MAXARGS
CALL GETARGS ;COLLECT COMMAND LINE ARGUMENTS
JNB L_2 ;IF OK
MOV AX,DGROUP
MOV DS,AX
MOV DX,OFFSET MSG5
CALL ERRORMSG ;TOO MANY ARGUMENTS
JMP EXIT2
L_2:
MOV AX,DGROUP
MOV DS,AX ;SET DATA SEG TO FIXED DATA
MOV WORD PTR NUMARGS,CX ;SAVE # OF ARGUMENTS
CMP CX,0
JNE L_2A ;IF SOME ARGUMENT
JMP START ;NO ARGUMENTS, USE STDIN
L_2A:
MOV SI,OFFSET ARGPTRS
MOV BX,WORD PTR [SI] ;POINT TO 1ST ARGUMENT
MOV AL,BYTE PTR [BX] ;GET 1ST CHAR.
CMP AL,'-'
JE L_3 ;IF SWITCH SPECIFIED
MOV SI,OFFSET ARGPTRS
MOV CX,WORD PTR NUMARGS ;GET # OF ARGUMENTS
JMP GETFILES
L_3:
INC BX
MOV CL,0
PUSH BX
CD: MOV AL,BYTE PTR [BX] ;HAVE NUMBER, COUNT NUMBER OF DIGITS
CMP AL,'0'
JC NODGT
CMP AL,'9'+1
JNC NODGT
INC BX
INC CL
JMP SHORT CD
NODGT:
POP BX
MOV CH,0 ;CL HOLDS DIGIT COUNT
CALL DTOBIN ;CONVERT NUMBER TO BINARY
JNC L_4 ;IF OK
JMP SHORT USE
L_4:
CMP AX,0 ;IS NUMBER 0?
JNE NOT0 ;NO.
JMP EXIT2 ;YES, IT IS, JUST EXIT
NOT0:
MOV WORD PTR NUMLIN,AX ;STORE # LINES
MOV SI,OFFSET ARGPTRS+2
MOV CX,WORD PTR NUMARGS ;GET # OF ARGUMENTS
DEC CX ;-1 CAUSE OF SWITCH
JMP SHORT GETFILES
USE:
MOV DX,OFFSET MSG4
CALL ERRORMSG ;TELL USER HOW TO USE
JMP EXIT2
START:
CALL HEAD
JMP EXIT2
GETFILES:
MOV AX,DGROUP
MOV DS,AX
CMP CX,0 ;NO FILE ARGUMENTS?
JNE GOT1
JMP START ;NO, JUST USE STDIN
GOT1:
CMP CX,1 ;>1 ARG?
JE ONLY1 ;NOPE
MOV BYTE PTR ONEFILE,0 ;>1 ARG
ONLY1:
ARGLUP: MOV BX,WORD PTR [SI] ;BX POINTS TO FILE NAME
PUSH CX
PUSH SI
CALL DOARG
POP SI
POP CX
SKIPSW:
ADD SI,2
LOOP ARGLUP
JMP EXIT2
; DOARG = PROCESS 1 ARGUMENT
; ES:BX POINTS TO IT
DOARG PROC NEAR
NONUM:
MOV AH,SET_DTA
MOV DX,OFFSET DTA
INT DOS ;SET DTA
MOV CX,OFFSET SPATH
MOV DX,OFFSET PREFIX
PUSH BX
CALL FIXPATH ;PARSE PATHNAME
POP BX
CMP AL,TYPE_UNK
JE BADNAME
CMP AL,TYPE_UFN
JE GOTNAME ;IF UNAMBIG. FILE NAME
MOV BYTE PTR ONEFILE,0 ;AMBIG. FILE NAME OR DIR, FLAG IT
JMP GOTNAME
BADNAME:
MOV DX,OFFSET MSG6
CALL ERRORMSG ;BAD FILE NAME, SHOW MSG.
MOV DX,BX
CALL ERRORMSG ;SHOW FILE THAT CAUSED IT
RET
GOTNAME:
MOV DX,OFFSET SPATH ;POINT TO SEARCH PATH
MOV CX,31H ;SET SEARCH ATTRIBUTES
MOV AH,FIND_FIRST
INT DOS ;SEARCH FOR 1ST MATCH
JB BADNAME ;IF NOTHING FOUND
GOTFILE:
MOV SI,OFFSET PREFIX
MOV DI,OFFSET FILENAME
MOV CX,65
CALL CPYCNT ;COPY PREFIX TO FILE NAME AREA
DEC DI ;BACK UP OVER NULL
MOV SI,(OFFSET DTA)+30 ;POINT TO FILE NAME WE FOUND
CMP [SI],BYTE PTR '.' ;DOES IT START WITH .? -
JNE NOTDOT ;- NO
JMP SHORT SKIPFILE ;YES, JUST SKIP IT
NOTDOT:
CALL CPYCNT ;COPY FILE WE FOUND AFTER PREFIX
CALL DOFILE ;DO 1 FILE
SKIPFILE:
MOV AH,FIND_NEXT
INT DOS ;FIND NEXT MATCH, IF ANY
JC NOMORE ;IF NONE
JMP GOTFILE ;GOT ONE, BACK TO TOP OF LOOP
NOMORE:
RET
DOARG ENDP
; DOFILE = PROCESS 1 FILE (NAME IN ES:FILENAME)
DOFILE PROC NEAR
MOV DX,OFFSET FILENAME ;DX POINTS TO FILE NAME
MOV AL,READ_ACCESS
MOV AH,DOS2_OPEN
INT DOS ;TRY TO OPEN FILE
JNC NAMEOK ;IF OK
JMP SHORT BADOPN
NAMEOK:
MOV WORD PTR INHANDLE,AX ;SAVE FILE HANDLE
CMP BYTE PTR ONEFILE,1
JE NOSHOW
CALL SHOWFILE ;SHOW FILE NAME (ONLY IF >1 SPECIFIED)
NOSHOW:
CALL HEAD ;SHOW HEAD OF FILE
RET
BADOPN:
MOV DX,OFFSET MSG1
CALL ERRORMSG ;BAD OPEN, SHOW MSG.
MOV DX,OFFSET FILENAME ;DX POINTS TO FILE NAME
CALL ERRORMSG ;SHOW IT
RET
DOFILE ENDP
; SHOW FILE NAME
SHOWFILE PROC NEAR
MOV AX,"="
MOV CX,5
BARS:
CALL WRITEBYTE
LOOP BARS
MOV AX,SPACE
CALL WRITEBYTE
MOV BX,OFFSET FILENAME
SHOWF: MOV AL,BYTE PTR [BX]
CMP AL,0
JE ENDF
CALL WRITEBYTE
INC BX
JMP SHOWF
ENDF: MOV AL,SPACE
CALL WRITEBYTE
MOV AL,'='
MOV CX,5
BARS2:
CALL WRITEBYTE
LOOP BARS2
MOV AL,CR
CALL WRITEBYTE
MOV AL,LF
CALL WRITEBYTE
RET
SHOWFILE ENDP
HEAD PROC NEAR
MOV CX,WORD PTR NUMLIN
NEWBUF:
CALL FILLBUF ;FILL INPUT BUFFER
JNB BEGIN ;IF OK
JMP BADREAD
BEGIN:
CMP BX,DX ;SEE IF ANYTHING READ
JE CLOSEFILE ;NO, ASSUME EOF
SHOW: CMP BX,DX ;DISPLAY TEXT - TOP OF LOOP
JGE NEWBUF ;IF END OF BUFFER
MOV AL,BYTE PTR [BX] ;GET CHAR. FROM BUFFER
INC BX ;BUMP POINTER
CALL WRITEBYTE ;WRITE CHAR. TO STDOUT
CMP AL,CTRL$Z ;TEST FOR ^Z
JE CLOSEFILE ;IF FOUND ^Z
CMP AL,CR ;IS CR?
JNE SHOW ;NOPE
LOOP SHOW ;YES, COUNT A LINE
; LINE COUNT REACHED
CMP BX,DX ;EXACTLY AT END OF BUFFER?
JNE NOTEND ;NO
CALL FILLBUF ;YES, JUST OUR LUCK, FILL IT AGAIN
JNB NOTEND
JMP SHORT BADREAD ;IF ERROR
NOTEND:
MOV AL,BYTE PTR [BX] ;GET CHAR. AFTER LAST CR
CMP AL,LF
JNE CLOSEFILE
CALL WRITEBYTE ;SHOW LF IF AFTER LAST CR
JMP CLOSEFILE
BADREAD:
MOV DX,OFFSET MSG2 ;SHOW ERROR
CALL ERRORMSG
MOV DX,OFFSET FILENAME
CALL ERRORMSG ;AND FILENAME
MOV DX,OFFSET MSG1E
CALL ERRORMSG ;AND CR/LF
CLOSEFILE:
MOV BX,WORD PTR INHANDLE
MOV AH,DOS2_CLOSE
INT DOS ;CLOSE INPUT FILE
EXIT1:
CALL FLUSH ;CLEAR OUTPUT BUFFER
RET
HEAD ENDP
; FILL BUFFER FROM DISK - RETURN 'C'=1 IF ERROR, BX = POINTER
; TO START OF BUFFER, DX = POINTER TO LAST CHAR + 1
FILLBUF PROC NEAR
PUSH CX ;SAVE LINE COUNT
MOV CX,INBUFSIZE ;CX = # BYTES TO READ
MOV BX,WORD PTR INHANDLE ;BX = FILE HANDLE
MOV DX,OFFSET INBUF
MOV AH,READ
INT DOS ;FILL BUFFER FROM FILE
POP CX ;RESTORE LINE COUNT
JC BAD ;IF ERROR
MOV BX,OFFSET INBUF
ADD AX,BX ;COMPUTE ADDR. OF LAST BYTE
MOV DX,AX ;SAVE IN DX
CLC
BAD:
RET
FILLBUF ENDP
; WRITE A BYTE TO THE OUTPUT
;
WRITEBYTE PROC NEAR
PUSH BX
PUSH CX
PUSH DX
MOV BX,WORD PTR OUTNDX
MOV BYTE PTR [BX+OUTBUF],AL
INC BX
MOV WORD PTR OUTNDX,BX
CMP BX,OUTBUFSIZE
JL NOTFUL
CALL FLUSH
NOTFUL:
POP DX
POP CX
POP BX
RET
WRITEBYTE ENDP
; FLUSH - WRITE OUTPUT BUFFER
FLUSH PROC NEAR
PUSH AX
MOV CX,WORD PTR OUTNDX
MOV DX,OFFSET OUTBUF
MOV BX,1
MOV AH,WRITE
INT DOS ;WRITE TO OUTPUT
POP AX
MOV WORD PTR OUTNDX,0
RET
FLUSH ENDP
EXIT2:
MOV AH,EXIT
INT DOS ;EXIT TO DOS
END ENTRY